#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * Hola
 * Primer cambio
 *
 * */

/* Tama�o del buffer temporal. */
#define LBUFFER 100

/* Buffer temporal. */
char buffer[LBUFFER];

/* M�xima nota posible */
#define MAXNOTA 10

/* Escribe un mensaje de error y sale del programa. */
void error(char *m)
  {
    fprintf(stderr, "Error: %s\n", m);
    exit(1);
  } /* error */

/* Sale del programa mostrando c�mo se utiliza. */
void errorUso()
  {
    error("Uso: estadisticas [-c <col>] <fich>\n");
  } /* errorUso */

/* Escribe un mensaje de error y aborta.
   Se utiliza para fallos del programa. */
void imposible()
  {
    fprintf(stderr, "Esto es imposible.\n");
    abort();
  } /* imposible */

/* Escribe un mensaje de aviso. */
void aviso(char *m)
  {
    fprintf(stderr, "Aviso: %s\n", m);
  } /* warning */

/* Devuelve el entero correspondiente a la cadena p*/

int aEntero(char *p)
  {
    int v; /* Valor del n�mero. */
    char *q; /* Recorre la cadena. */

    /* La cadena no puede estar vac�a. */
    if ( *p== '\0' )
      {
        aviso("Se ha pasado una cadena vac�a como n�mero, se toma como cero");
        return 0;
      }

    /* Calculamos el valor. */
    v= 0;
    q= p;
    while ( isdigit(*q) )
      {
        v= *q-'0';
        q++;
      }
    /* Avisamos si ha habido alg�n error. */
    if ( *q!= '\0' )
      {
        sprintf(buffer, "Se ha transformado \"%.10s\" en el entero %d", p, v);
        aviso(buffer);
      }
    return v;
  } /* aEntero */

/* Lee una l�nea del fichero f. Devuelve una copia o NULL si el fichero
   ya se ha terminado. */
char *leeLinea(FILE *f)
  {
    if (!fgets(buffer, LBUFFER, f))
      return NULL;
    return strdup(buffer);
  }

/* Devuelve una copia del campo c de la cadena p. Se usa d como
   separador de campos y se cuenta desde 0. */

char *campo(char *p, int c, char d)
  {
    int n, /* Campo actual. */
      l; /* Longitud del campo c. */
    char *q, /* Recorre la cadena. */
      *r, /* Copia del campo c (resultado). */
      *s; /* Comienzo del campo c. */

    /* Buscamos el comienzo del campo c. */
    q= p;
    n= 0;
    if ( n!= c )
    while ( *q!= '\0' )
      if ( *q++== d )
        {
          n++;
          if ( n== c )
            break;
        }

    /* Si no hemos encontrado el campo c, devolvemos NULL. */
    if ( n!= c )
      return NULL;

    /* Guardamos el comienzo y la longitud del campo. */
    s= q;
    l= 0;
    while ( *q!= '\0' && *q!= d && *q!= '\n' )
      l++, q++;

    /* Hacemos la copia. */
    r= (char *)malloc(l+1);
    strcpy(r, s);
    return r;
  } /* campo */

/* Procesa el fichero f para recopilar las estad�sticas del campo
   c. Despu�s las escribe en el fichero salida. */
void procesaFichero(FILE *f, int c, FILE *salida)
  {
    char *l, /* L�nea le�da. */
      *cc; /* Copia del campo. */
    int nl, /* N�mero de l�nea le�da. */
      min= MAXNOTA, /* M�nima nota. */
      max= 0, /* M�xima nota. */
      nn= 0, /* N�mero de notas. */
      sn= 0, /* Suma de las notas. */
      nota; /* Nota le�da. */

    /* Leemos l�nea a l�nea. */
    nl= 0;
    while ( (l= leeLinea(f))!= NULL )
      {
        nl++; /* Hemos le�do otra l�nea. */
        cc= campo(l, c, '\t'); /* Recuperamos el campo. */
        /* Comprobamos que el campo existe. */
        if ( cc== NULL )
          {
            sprintf(buffer, "La l�nea %d no tiene nota", nl);
            aviso(buffer);
            free(l);
            continue;
          }
        /* Transformamos el campo en entero y nos aseguramos de que
           est� en el rango. */
        nota= aEntero(cc);
        if ( nota> MAXNOTA )
          {
            sprintf(buffer, "Nota muy alta (%d) en la l�nea %d", nota, nl);
            aviso(buffer);
            free(cc);
            free(l);
            continue;
          }
        /* Actualizamos las estad�sticas.*/
        sn+= nota;
        if ( nota< min )
          min= nota;
        if ( max< nota )
          max= nota;
        nn++;
        /* Liberamos la memoria de la l�nea. */
        free(l);
      }
    if ( nn> 0 )
      {
        fprintf(salida, "Resultados:\n");
        fprintf(salida, "==========\n");
        fprintf(salida, "Mejor nota: %d\n", max);
        fprintf(salida, "Peor nota: %d\n", min);
        fprintf(salida, "Media: %4.1f\n", sn/nn);
      }
    else
      error ("No he encontrado ninguna nota");
  } /* procesaFichero */

/* El programa principal */

int main (int argc, char *argv[])
  {
    int arg, /* Argumento que se va a analizar. */
      c= 0; /* Campo de las notas. Por defecto es 0, el primer campo. */
    FILE *f; /* Fichero de entrada. */

    /* Comprobamos si se ha pasado la opci�n -c. */
    arg= 1;
    if ( arg< argc && argv[arg][0]== '-' )
      {
        if ( argv[arg][1]!= 'c' )
          errorUso();
        /* El n�mero de campo puede estar pegado a -c (if) o separado (else) */
        if ( argv[arg][2]!= '\0' )
          c= aEntero(argv[arg]+2);
        else
          {
            arg++;
            if ( arg>= argc )
              errorUso();
            c= aEntero(argv[arg]);
          }
        arg++;
        c--; /* Restamos uno porque los campos se numeran internamente desde cero. */
      }
    if ( arg== argc )
      f= stdin; /* Si no hay par�metros, se lee de stdin. */
    else
      {
        if ( arg!= argc-1 ) /* Puede haber como mucho un fichero. */
          errorUso();
        f= fopen(argv[arg], "r");
        if ( f== NULL ) /* Error si no podemos abrir el fichero. */
          {
            sprintf(buffer, "No he podido abrir el fichero %.20s", argv[arg]);
            error(buffer);
          }
      }
    procesaFichero(f, c, stdout);
    return 0;
  } /* main */
